接下來繼續介紹一個也很實用的功能,曝光度調整。
一樣傳入 Uint8ClampArray
,並且將透過 amount
來調整亮度 ( 使用的區間是 -100 ~ 100 ),大於 0 就是增加亮度, 反之則是降低。通過一次增加三個通道的值讓畫面顯得更亮是最簡單的演算法,實做也很簡單如下
export const brightness = (pixelData, amount) => {
// 每次跳四個索引,也就是一個像素,不處理透明度
for (let i = 0; i < pixelData.length; i += 4) {
pixelData[i] = pixelData[i] + amount // red
pixelData[i + 1] = pixelData[i + 1] + amount // green
pixelData[i + 2] = pixelData[i + 2] + amount // blue
}
return pixelData
}
接下來我們做一個簡易的 Slider 來更好操控。這邊為了快速就直接套用 element UI,詳細用法請參照官網。因為接下來會大量使用到這個元件,所以在包了一層方便使用。
<div class="slider">
<span>{{ title }}</span>
<el-slider
:value="value"
:min="min"
:max="max"
@input="handleChange"
></el-slider>
</div>
在外層中使用
<Slider
title="曝光度"
:min="-100"
:max="100"
:value="brightness"
@sliderChange="val => sliderChange(val, 'brightness')"
></Slider>
接下來把這些透過 Slider 調整的參數以及一開始獲得的 ImageData
放到 Store
裡面方便之後使用。所以當滑動更新參數時,editImageData
,也會相對應更新。
state: {
sliderValue: {
brightness: 0
},
originalEditData: {}
},
mutations: {
CHANGE_STATE_VALUE(state, { key, val }) {
if (state[key] !== undefined) {
state[key] = val
}
},
CHANGE_SLIDER_VALUE(state, { key, val }) {
if (state.sliderValue[key] !== undefined) {
state.sliderValue[key] = val
}
}
},
getters: {
editImageData({ sliderValue, originalEditData }) {
if (sliderValue.brightness !== 0) {
filters.brightness(originalEditData.data, sliderValue.brightness)
}
return originalEditData
}
}
}
接下來我們在 watch
更新過後的資料,並且重新繪製到 Canvas
上就可以了
watch: {
editImageData(pixelData) {
const canvas = this.$refs.drawCanvas
const context = canvas.getContext('2d')
context.putImageData(pixelData, 0, 0)
}
}
到這邊應該基本的流程已經建立完成,有一些過於瑣碎的傳遞資料處理就不再詳細說明,讀者可能自行需要補足一些地方。到這邊如果沒問題的話,效果應該會如下
一開始好像還算正常,但到後面拖回去原始的值時候卻發現回不去了~
因為在 editImageData
裡面,我們是直接對原始的值做處理,所以假設原本的值是這樣好了
[180, 170, 160, 255]
當今天是通通加 100 時會變成
// 雖然實際上 + 100 的值不會是這樣,但還記得之前說過的特性嗎,超過 255 的值會被縮成 255
[255, 255, 255, 255]
也就是說,就算你這時候在往回調,原本的顏色就跟變了心的女朋友一樣回不來了,所以我們修改一下,當需要做運算處理時,我們都複製一份原始的資料,每一次都使用原始的資料做運算
editImageData({ sliderValue, originalEditData }) {
if (originalEditData.data) {
const imageDataCopy = new ImageData(
new Uint8ClampedArray(originalEditData.data),
originalEditData.width,
originalEditData.height
)
if (sliderValue.brightness !== 0) {
filters.brightness(imageDataCopy.data, sliderValue.brightness)
}
return imageDataCopy
}
}
看一下成果
今天介紹了常用的曝光度調整,以及把一些基本的元件、流程建立起來,方便之後擴增,明天見!